package com.iwords.android;

import java.io.InputStream;
import java.net.URL;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xmlpull.v1.XmlPullParser;

import android.util.Xml;

/**
 * DictCN提供XML格式数据接口。
 */
public class ParserDictCNXML {
	public static WordIllustration parseByAndroidParser(String word)
			throws Exception {
		String qurl = "http://dict.cn/ws.php?utf8=true&q="+ CodeUtils.encode(word);
		//System.out.println("ParserDictCNXML.parseByAndroidParser()! qurl = "+ qurl);
		URL url = new URL(qurl);
		InputSource is = new InputSource(url.openStream());
		is.setEncoding("utf-8");
		return parseXml(is.getByteStream());
	}

	public static WordIllustration parseBySAX(String word) throws Exception {
		WordIllustration wi = new WordIllustration();
		String qurl = "http://dict.cn/ws.php?utf8=true&q=" + CodeUtils.encode(word);
		//System.out.println("ParserDictCNXML.parseBySAX()! qurl = " + qurl);
		URL url = new URL(qurl);
		InputSource is = new InputSource(url.openStream());
		is.setEncoding("utf-8");
		// long time = System.currentTimeMillis();
		// System.out.println(time);
		SAXParserFactory factory = SAXParserFactory.newInstance();
		SAXParser parser = factory.newSAXParser();
		XMLReader xmlreader = parser.getXMLReader();
		xmlreader.setContentHandler(new DictCNHandler(wi));
		xmlreader.parse(is);
		return wi;
	}

	/** 有时候XML解析出错，换用不同的Parser试验两次 */
	public static WordIllustration query(String word) {
		try {
			return parseByAndroidParser(word);
		} catch (Exception e) {
			e.printStackTrace();
		}
		try {
			return parseBySAX(word);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * pull方式解析xml实现方法
	 * 
	 * @param is
	 *            xml的输入流形式
	 * @return 返回解析后的对象集合
	 * @throws Exception
	 */
	public static WordIllustration parseXml(InputStream is) throws Exception {

		// 创建pull解析对象
		XmlPullParser parser = Xml.newPullParser();

		// 将xml文件以输入流的形式传递给 pull解析对象，并设置解析对象按照 utf-8 的编码进行解析
		parser.setInput(is, "utf-8");

		// pull解析对象在解析xml时，会返回一个代表解析位置的值。
		// START_DOCUMENT ： 开始解析文档
		// START_TAG ： 开始解析标签
		// END_TAG : 标签结束
		// END_DOCUMENT ：xml文档解析结束
		// 得到当前解析的位置
		int type = parser.getEventType();

		WordIllustration word = new WordIllustration();
		String en = "";
		String cn = "";
		// 当没有解析的文档的末尾的时候，一直执行
		while (type != XmlPullParser.END_DOCUMENT) {

			// switch 解析的位置
			switch (type) {
			// 开始解析文档的时候，初始化对象集合
			case XmlPullParser.START_DOCUMENT:
				word = new WordIllustration();
				break;

			// 开始解析标签的时候，根据标签的不同名称。做不同操作
			case XmlPullParser.START_TAG:
				// 标签为person的时候，取出标签的属性id值，并保存到Person对象里
				if ("key".equals(parser.getName())) {
					word.setSpelling(parser.nextText());
				} else if ("pron".equals(parser.getName())) {
					word.setPhonetics(parser.nextText());
				} else if ("def".equals(parser.getName())) {
					word.setMeaning(parser.nextText());
				} else if ("sent".equals(parser.getName())) {
					en = "";
					cn = "";
				} else if ("orig".equals(parser.getName())) {
					en = parser.nextText().replaceAll("<em>", "<b>").replaceAll("</em>", "</b>");
				} else if ("trans".equals(parser.getName())) {
					cn = parser.nextText();
				}
				break;

			// 当解析到标签结束的时候执行
			case XmlPullParser.END_TAG:
				// 如果结束标签名是sent，那么就是一个新的例句结束，讲例句加入word
				if ("sent".equals(parser.getName())) {
					word.getSentences().add(
							new WordIllustration.Sentence(en, cn));
				}

				break;
			}

			// 当前解析位置结束，指向下一个位置
			type = parser.next();
		}
		is.close();
		// 返回对象数组
		return word;
	}

	static class DictCNHandler extends DefaultHandler {

		boolean key = false;
		boolean audio = false;
		boolean pron = false;
		boolean rel = false;
		boolean def = false;
		boolean orig = false;
		boolean trans = false;
		boolean em = false;

		WordIllustration wi;
		StringBuilder spelling = new StringBuilder();
		StringBuilder audioURL = new StringBuilder();
		StringBuilder pronuciation = new StringBuilder();
		StringBuilder define = new StringBuilder();
		StringBuilder sentenceOrignal = new StringBuilder();
		StringBuilder sentenceTranslation = new StringBuilder();

		public DictCNHandler(WordIllustration wi) {
			this.wi = wi;
		}

		public void startElement(String uri, String localName, String qName,
				Attributes attributes) throws SAXException {

			// System.out.println("Start Element :" + qName);
			if (qName.equalsIgnoreCase("key")) {
				key = true;
			} else if (qName.equalsIgnoreCase("audio")) {
				audio = true;
			} else if (qName.equalsIgnoreCase("pron")) {
				pron = true;
			} else if (qName.equalsIgnoreCase("rel")) {
				rel = true;
			} else if (qName.equalsIgnoreCase("def")) {
				def = true;
			} else if (qName.equalsIgnoreCase("orig")) {
				orig = true;
			} else if (qName.equalsIgnoreCase("trans")) {
				trans = true;
			}
		}

		public void endElement(String uri, String localName, String qName)
				throws SAXException {
			if ("sent".equals(qName)) {
				wi.getSentences().add(
						new WordIllustration.Sentence(sentenceOrignal
								.toString().replaceAll("<em>", "<b>").replaceAll("</em>", "</b>"),
								sentenceTranslation.toString()));
				sentenceOrignal.setLength(0);
				sentenceTranslation.setLength(0);
			} else if ("key".equals(qName)) {
				wi.setSpelling(spelling.toString());
				key = false;
			} else if ("audio".equals(qName)) {
				wi.setAudioURL(audioURL.toString());
				audio = false;
			} else if ("pron".equals(qName)) {
				wi.setPhonetics(pronuciation.toString());
				pron = false;
			} else if ("rel".equals(qName)) {
				// wi.setMeaning(define);
				rel = false;
			} else if ("def".equals(qName)) {
				wi.setMeaning(define.toString());
				def = false;
			} else if ("orig".equals(qName)) {
				orig = false;
			} else if ("trans".equals(qName)) {
				trans = false;
			}
			// System.out.println("End Element :" + qName);
		}

		public void ignorableWhitespace(char[] ch, int start, int length) {
			//System.out.println("ignorableWhitespace ch = " + new String(ch));
			//System.out.println("ignorableWhitespace start = " + start);
			//System.out.println("ignorableWhitespace length = " + length);
		}

		public void characters(char ch[], int start, int length)
				throws SAXException {
			// System.out.println("---------------length="+length+" start="+start+" ch[]="+new
			// String(ch, start, length));
			if (key) {
				spelling.append(ch, start, length);
				// System.out.println("spelling="+spelling);
			} else if (audio) {
				audioURL.append(ch, start, length);
				// System.out.println("audio="+audioURL);
			} else if (pron) {
				pronuciation.append(ch, start, length);
				// System.out.println("pron="+pronuciation);
			} else if (rel) {
				// pronuciation = new String(ch, start, length);
				// System.out.println("rel="+new String(ch, start, length));
			} else if (def) {
				define.append(ch, start, length);
				// System.out.println("def="+define);
				// System.out.println("ch.length="+ch.length+" ch["+(ch.length-1)+"]="+ch[ch.length-1]);
			} else if (orig) {
				sentenceOrignal.append(ch, start, length);
				// System.out.println("orig="+sentenceOrignal);
			} else if (trans) {
				sentenceTranslation.append(ch, start, length);
				// System.out.println("trans="+sentenceTranslation);
			}
		}

	}
}

/**
 * Dict.cn的XML接口格式 <dict> <key>word</key> <lang>ec</lang>
 * <audio>http://mp3.dict.cn/mp3.php?q=efVw7</audio> <pron>w&#601;:d</pron>
 * <def>n.单词,消息,话语,诺言 vt.用词语表达</def> <sent><orig>Could we have a
 * &lt;em&gt;word&lt;/em&gt; before you go to the
 * meeting?</orig><trans>你去开会之前，咱们能私下说句话吗？</trans></sent> <sent><orig>Tell me
 * what happened in your own
 * &lt;em&gt;words&lt;/em&gt;.</orig><trans>用你自己的话把发生的事情告诉我。</trans></sent>
 * <sent><orig>My friend sent &lt;em&gt;word&lt;/em&gt; that he was
 * well.</orig><trans>我朋友捎来口信说他很好。</trans></sent> </dict>
 */
